#include "MeleeEnemy.h"

MeleeEnemy::MeleeEnemy(void){
	this->InitSprite(11);
	this->SetSprite(0, "images/Enemy/Minion/Melee/enemyIdle1.tga");
	this->SetSprite(1, "images/Enemy/Minion/Melee/enemyAttack1.tga");
	this->SetSprite(2, "images/Enemy/Minion/Melee/enemyAttack2.tga");
	this->SetSprite(3, "images/Enemy/Minion/Melee/enemyAttack3.tga");
	this->SetSprite(4, "images/Enemy/Minion/Melee/enemyAttack4.tga");
	this->SetSprite(5, "images/Enemy/Minion/Melee/enemyWalking1.tga");
	this->SetSprite(6, "images/Enemy/Minion/Melee/enemyWalking2.tga");
	this->SetSprite(7, "images/Enemy/Minion/Melee/enemyWalking3.tga");
	this->SetSprite(8, "images/Enemy/Minion/Melee/enemyWalking4.tga");
	this->SetSprite(9, "images/Enemy/Minion/Melee/enemyDefend1.tga");
	this->SetSprite(10, "images/Enemy/Minion/Melee/enemyDefend2.tga");
	this->Init(Vector3D(0, 400, 0), 45, 60);
	this->SetLife(10.0f);
	this->SetAttackDamage(0.5f);

	weapon.InitSprite(2);
	weapon.SetSprite(0, "images/Enemy/Minion/Melee/slash1.tga");
	weapon.SetSprite(1, "images/Enemy/Minion/Melee/slash2.tga");
	weapon.Init(this->GetPosition(), this->GetWidth(), this->GetHeight());

	spaceCheck.InitBox(this->GetPosition(), 2.0, this->GetHeight() / 2, 1.0);

	attackStart = false;
	attackTime = false;
	idleTime = false;
	defendTime = false;
	retreatTime = false;

	this->SetSpeed(100.0f);
	this->SetLengthOfSight(LINE_OF_SIGHT);

	rndNum = rand() % 3 + 1;
	switch(rndNum){
		case 1:
			perType = CAREFUL;
			//cout << "Care" << endl;
			break;
		case 2:
			perType = BRAVE;
			//cout << "Brave" << endl;
			break;
		case 3:
			perType = TIMID;
			//cout << "Timid" << endl;
			break;
	}
	
	curState = IDLE;
	newState = IDLE;
}

MeleeEnemy::~MeleeEnemy(void){
}

void MeleeEnemy::BraveAI(float elapsed){
	if(enemyDetected || attackStart){
		newState = ATTACK;
	}else{
		newState = IDLE;
	}
}

void MeleeEnemy::CarefulAI(float elapsed){
	if(!attackStart){
		if(enemyDetected || defendTime){
			newState = DEFEND;
		}else{
			newState = IDLE;
		}
	}else{
		newState = ATTACK;
	}
}

void MeleeEnemy::TimidAI(float elapsed){
	if(enemyDetected || attackStart){
		newState = CHECK;
	}else if(!retreatTime){
		newState = IDLE;
	}
}

void MeleeEnemy::Idle(void){
	if(this->GetOnGround()){
		if(!idleTime){
			this->SetSpriteImageNumber(0);

			for(vector<Object *>::iterator itr = TargetInfoList.begin(); itr != TargetInfoList.end(); ++itr){
				if(!(*itr)->GetBoundingBox(Object::FULLBODY).HitTest(this->GetBoundingBox(Object::FULLBODY))){
					rndNum = rand() % 100 + 1;
					if(rndNum < 25){
						this->SetDirection(Vector3D());
					}else{
						rndNum = rand() % 100 + 1;

						if(rndNum < 50)
							this->SetDirection(Vector3D(1.0, this->GetDirection().y, 0.0));
						else
							this->SetDirection(Vector3D(-1.0, this->GetDirection().y, 0.0));
					}
				}else{
					this->SetDirection(Vector3D());
				}
			}

			countdownTimer.StartTimer(0, 0, 5, 0);
			idleTime = true;
		}

		if(idleTime && countdownTimer.CheckIfTimerEnd()){
			//countdownTimer.StartTimer(0, 0, 5, 0);
			idleTime = false;
		}
	}
}

void MeleeEnemy::Attack(void){
	if(!attackStart){
		for(vector<Object *>::iterator itr = TargetInfoList.begin(); itr != TargetInfoList.end(); ++itr){
			//delete (*itr);

			if(this->weapon.GetBoundingBox(Object::FULLBODY).HitTest((*itr)->GetBoundingBox(Object::FULLBODY))){
				this->SetDirection(Vector3D());

				this->SetSpriteImageNumber(0);
				countdownTimer.StartTimer(0, 0, 0, 500);

				weapon.invertImage = this->invertImage;

				attackStart = true;
			}
		}
	}

	if(attackStart && countdownTimer.CheckIfTimerEnd()){
		this->PlaySpriteAnimation(1, 4, 500);

		if(this->GetSpriteImageNumber() == 2){
			attackTime = true;
			renderWeapon = true;
		}else if(this->GetSpriteImageNumber() == 4){
			attackTime = false;
			renderWeapon = false;
		}

		if(this->animationFinished){
			attackStart = false;
			this->SetSpriteImageNumber(0);
			newState = IDLE;
		}else if(attackTime){
			weapon.PlaySpriteAnimation(0, 1, 500);
		}
	}
}

void MeleeEnemy::CheckForAllies(void){
	if(Board->SearchPost("ATTACK", Message::ENEMY) || Board->SearchPost("DEFEND", Message::ENEMY))
		newState = ATTACK;
	else
		newState = RETREAT;
}

void MeleeEnemy::Retreat(void){
	if(!retreatTime){
		retreatTime = true;
		countdownTimer.StartTimer(0, 0, 3, 0);
		this->SetDirection(Vector3D(this->GetDirection().x * -1, this->GetDirection().y, 0.0));
	}

	if(retreatTime && countdownTimer.CheckIfTimerEnd()){
		newState = IDLE;
		retreatTime = false;
	}
}

void MeleeEnemy::Defend(void){
	if(!defendTime){
		for(vector<Object *>::iterator itr = TargetInfoList.begin(); itr != TargetInfoList.end(); ++itr){
			this->SetDirection(Vector3D());

			defendTime = true;
			this->SetSpriteImageNumber(0);

			countdownTimer.StartTimer(0, 0, 0, 500);
		}
	}

	/*if(!defendTime && playerInfo->GetBoundingBox(Object::FULLBODY).HitTest(this->weapon.GetBoundingBox(Object::FULLBODY))){
		this->SetDirection(Vector3D());

		defendTime = true;
		this->SetSpriteImageNumber(0);

		countdownTimer.StartTimer(0, 0, 0, 500);
	}else if(extraTarget){
		if(!defendTime && target->GetBoundingBox(Object::FULLBODY).HitTest(this->weapon.GetBoundingBox(Object::FULLBODY))){
			this->SetDirection(Vector3D());

			defendTime = true;
			this->SetSpriteImageNumber(0);

			countdownTimer.StartTimer(0, 0, 0, 500);
		}
	}*/

	if(defendTime && countdownTimer.CheckIfTimerEnd()){
		this->PlaySpriteAnimation(9, 10, 500);
		
		if(this->animationFinished){
			defendTime = false;
			this->SetSpriteImageNumber(0);
			newState = ATTACK;
		}
	}
}

void MeleeEnemy::DropItemOnDeath(vector<PickUp *> *PickUpList){
	if(rand() % 100 + 1 < 25){
		this->CreatePickUp(Vector3D(this->GetPosition().x + this->oOff.x
									, this->GetPosition().y + this->oOff.y
									, this->GetPosition().z + this->oOff.z)
									, Item::no::SWORDPIECE, PickUpList);
	}

	if(rand() % 100 + 1 < 50){
		this->CreatePickUp(Vector3D(this->GetPosition().x + this->oOff.x + 30
									, this->GetPosition().y + this->oOff.y
									, this->GetPosition().z + this->oOff.z)
									, Item::no::LEATHER, PickUpList);
	}

	return;
};

bool MeleeEnemy::UpdateObject(Vector3D offset, float elapsed){
	Enemy::UpdateObject(offset, elapsed);

	if(attackTime){
		/*if(weapon.GetBoundingBox(Object::FULLBODY).HitTest(playerInfo->GetBoundingBox(Object::FULLBODY))){
			playerInfo->ReduceLife(this->GetAttackDamage());
		}else{*/
			for(vector<Object *>::iterator itr = TargetInfoList.begin(); itr != TargetInfoList.end(); ++itr){
				if(weapon.GetBoundingBox(Object::FULLBODY).HitTest((*itr)->GetBoundingBox(Object::FULLBODY))){
					(*itr)->ReduceLife(this->GetAttackDamage());
				}
			}
		//}

		weapon.UpdateObject(offset, elapsed);
	}

	if(curState != newState){
		countdownTimer.StopTimer();
		curState = newState;

		switch(newState){
			case IDLE:
				Board->SetMessage("IDLE", Message::ENEMY, id);
				break;
			case ATTACK:
				Board->SetMessage("ATTACK", Message::ENEMY, id);
				break;
			case DEFEND:
				Board->SetMessage("DEFEND", Message::ENEMY, id);
				break;
			case RETREAT:
				Board->SetMessage("RETREAT", Message::ENEMY, id);
				break;
			case CHECK:
				Board->SetMessage("CHECk", Message::ENEMY, id);
				break;
		}
	}

	switch(perType){
		case BRAVE:
			BraveAI(elapsed);
			break;
		case CAREFUL:
			CarefulAI(elapsed);
			break;
		case TIMID:
			TimidAI(elapsed);
			break;
	}

	switch(curState){
		case IDLE:
			Idle();
			break;
		case ATTACK:
			Attack();
			break;
		case DEFEND:
			Defend();
			break;
		case RETREAT:
			Retreat();
			break;
		case CHECK:
			CheckForAllies();
			break;
	}

	return false;
}